package laxmysql

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "go.uber.org/zap"
)

// @Desc: 解析xml配置
type LaxMySQLConfig struct {
    // 用于在多个的时候定位一下
	Id string `xml:"id,attr"`
    // 数据库地址
    Host string `xml:"addr,attr"`
    // 数据库端口
    Port int32 `xml:"port,attr"`
    // 数据库用户
    User string `xml:"user,attr"`
    // 数据库密码
    Password string `xml:"password,attr"`
    // 要转接头的数据库
    Database string `xml:"database,attr"`
}

// @Desc: 序列化输出
// @receiver cfg xml配置
// @return string  序列化后的字符串
func (cfg *LaxMySQLConfig) ToString() string {
    return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s",
        cfg.User,
        cfg.Password,
        cfg.Host,
        cfg.Port,
        cfg.Database)
}

type (
    // 查询单行数据的回调
    MySQLRowCallback func(row *sql.Row) error
    // 查询多行数据的回调
    MySQLRowsCallback func(row *sql.Rows) error
    /*
    // 基类
    IBaseMySQLConn interface {
        // 执行(insert, update, delete)，会以事务形式执行
        Execute(execStmt string, args ...interface{}) (int64, error)
        // 查询单行
        QueryRow(queryStmt string, callback MySQLRowCallback, args ...interface{}) error
        // 查询多行
        Query(queryStmt string, callback MySQLRowsCallback, args ...interface{}) error
        // 关闭连接
        Close()
    }
     */
    // 个人使用的mysql连接
    LaxMySQLConn struct {
        *sql.DB
        id string
    }
)

// @Desc: 创建一个新的数据库连接
// @param cfg 相应配置
// @return *LaxMySQLConn 数据库连接
// @return error
func NewMySQLConn(cfg *LaxMySQLConfig) (*LaxMySQLConn, error) {
    if db, err := sql.Open("mysql", cfg.ToString()); err != nil {
        return nil, err
    } else if err = db.Ping(); err != nil {
        return nil, err
    } else {
        return &LaxMySQLConn{
            DB: db,
            id: cfg.Id,
        }, nil
    }
}

func (c *LaxMySQLConn) TranslateBegin() {

}

// @Desc: 执行单条语句
// @receiver c
// @param execStmt
// @param args
// @return int64
// @return error
func (c *LaxMySQLConn) LaxExecute(execStmt string, args ...interface{}) (int64, error) {
    result, err := c.Exec(execStmt, args...)
    if err != nil {
        return 0, err
    }
    rowsAffect, err := result.RowsAffected()
    if err != nil {
        return 0, err
    }
    return rowsAffect, nil
}

func (c *LaxMySQLConn) LaxQueryRow(queryStmt string, callback MySQLRowCallback, args ...interface{}) error {
    row := c.DB.QueryRow(queryStmt, args...)
    if row.Err() != nil {
        return row.Err()
    }
    if callback != nil {
        if err := callback(row); err != nil {
            return err
        }
    }
    return nil
}

// @Desc:
// @receiver c
// @param queryStmt
// @param callback
// @param args
// @return error
func (c *LaxMySQLConn) LaxQuery(queryStmt string, callback MySQLRowsCallback, args ...interface{}) error {
    rows, err := c.DB.Query(queryStmt, args...)
    if err != nil {
        return err
    }
    defer rows.Close()
    if callback != nil {
        for rows.Next() {
            if err = callback(rows); err != nil {
                return err
            }
        }
    }
    return nil
}

// @Desc: 断开连接
// @receiver c
func (c *LaxMySQLConn) Close() {
    zap.S().Infof("[数据库] id[%s] 关闭", c.id)
    c.DB.Close()
}

/// 获取id
func (c *LaxMySQLConn) GetId() string {
    return c.id
}
